package uk.ac.cam.cl.oscar;

import uk.ac.cam.cl.oscar.sift.*;

import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Vector;
import javax.imageio.*;
import uk.ac.cam.cl.oscar.edgefinder.*;
import java.awt.*;

public class ComplexImageTests
{
    public static final String path = "tests/";

    public static void main(String args[]) {
        Vector<Vector<Keypoint>> low = new Vector<Vector<Keypoint>>();
        Vector<Vector<Keypoint>> high = new Vector<Vector<Keypoint>>();
        for (int i=1; i<4; i++) {
            try {
                File f = new File(path + "3low" + i + ".jpg");
                BufferedImage img = ImageIO.read(f);
                Vector<Keypoint> kplist = SIFT.findKeypoints(img);
                low.add(kplist);
                System.out.println("Found " + kplist.size() + " keypoints");
                f = new File(path + "2low" + i + ".jpg");
                img = ImageIO.read(f);
                kplist = SIFT.findKeypoints(img);
                System.out.println("Found " + kplist.size() + " keypoints");
                high.add(kplist);
            } catch (IOException e) { System.out.println(e); }
        }

        for (int i=0; i<3; i++) {
            double matchcount = 10.0, matchcount2 = 10.0, matchcount3 = 10.0;
            int bestid = 0;
            int bestid2 = 0;
            int bestid3 = 0;
            Vector<KeypointMatch> bestmatches = null, bestmatches2 = null, bestmatches3 = null;
            System.out.println("Matching for Image " + i);
            for (int n=0; n<3; n++) {
                System.out.println("Low size: " + low.elementAt(i).size());
                Vector<KeypointMatch> matches = KeypointMatcher.findMatches(high.elementAt(n), low.elementAt(i));
                System.out.println("Low: " + i + " High: " + n + " Matches: " + matches.size());
                double dist = 0.0;
                for (int m=0; m<matches.size(); m++) {
                    dist += matches.elementAt(m).getDistance();
                }
                System.out.println("Match distance: " + dist);
                if ((dist / matches.size()) < matchcount) {
                    bestid3 = bestid2;
                    matchcount3 = matchcount2;
                    bestmatches3 = bestmatches2;
                    bestid2 = bestid;
                    matchcount2 = matchcount;
                    bestmatches2 = bestmatches;
                    matchcount = dist / matches.size();
                    bestmatches = matches;
                    bestid = n;
                    System.out.println("New best: " + n);
                }
            }
            try {
               System.out.println("Best: " + bestid);
               int id = bestid + 1;
               File nf = new File(path + "3low" + (i+1) + ".jpg");
               BufferedImage nimg = ImageIO.read(nf);
               nf = new File(path + "2low" + id + ".jpg");
               BufferedImage img = ImageIO.read(nf);
               BufferedImage out = new BufferedImage(Math.max(img.getWidth(), nimg.getWidth()), 
                                                     img.getHeight()+nimg.getHeight(),
                                                     BufferedImage.TYPE_INT_RGB);
               for (int y=0; y<out.getHeight(); y++) {
                   for (int x=0; x<out.getWidth(); x++) {
                       out.setRGB(x,y,0);
                   }
               }
               for (int y=0; y<img.getHeight(); y++) {
                   for (int x=0; x<img.getWidth(); x++) {
                       out.setRGB(x,y,img.getRGB(x,y));
                   }
               }
               for (int y=img.getHeight(); y<out.getHeight(); y++) {
                   for (int x=0; x<nimg.getWidth(); x++) {
                       out.setRGB(x,y,nimg.getRGB(x,y-img.getHeight()));
                   }
               }
               for (int n=0; n<high.elementAt(i).size(); n++) {
                   Keypoint kp = high.elementAt(i).elementAt(n);

                   int x = (int)Math.round(kp.getX());
                   int y = (int)Math.round(kp.getY());

                   out.setRGB(x,y,0xFF0000 + (int)Math.round(50 * (kp.getScale()-0.5)));
               }
               for (int n=0; n<low.elementAt(bestid).size(); n++) {
                   Keypoint kp = low.elementAt(bestid).elementAt(n);

                   int x = (int)Math.round(kp.getX());
                   int y = (int)Math.round(kp.getY());

                   out.setRGB(x,y+img.getHeight(),0xFF0000 + (int)Math.round(50 * (kp.getScale()-0.5)));
               }
               Graphics2D g2d = out.createGraphics();
               for (int n=0; n<bestmatches.size(); n++) {
                   KeypointMatch kpm = bestmatches.elementAt(n);
                   Keypoint kp1 = kpm.getKeypoint2(), kp2 = kpm.getKeypoint1();

                   g2d.drawLine((int)Math.round(kp1.getX()), (int)Math.round(kp1.getY()),
                                (int)Math.round(kp2.getX()), (int)Math.round(kp2.getY())+img.getHeight());
               }

               File outputfile = new File(path + "result" + i + ".jpg");
               ImageIO.write(out, "jpg", outputfile);
            } catch (IOException e) { System.out.println(e); }
        }
    }
}
